package cn.microservices.cloud.common.mybtis.interceptors;//package cn.microservices.supplychain.commons.interceptors;
//
//import cn.hutool.core.bean.BeanUtil;
//import cn.hutool.crypto.digest.MD5;
//import cn.hutool.extra.spring.SpringUtil;
//import com.alibaba.fastjson.JSONObject;
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.google.common.base.CaseFormat;
//import lombok.extern.slf4j.Slf4j;
//import net.sf.jsqlparser.JSQLParserException;
//import net.sf.jsqlparser.parser.CCJSqlParserUtil;
//import net.sf.jsqlparser.util.TablesNamesFinder;
//import org.apache.ibatis.binding.MapperMethod;
//import org.apache.ibatis.executor.Executor;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.mapping.ParameterMapping;
//import org.apache.ibatis.plugin.*;
//import org.apache.ibatis.session.ResultHandler;
//import org.apache.ibatis.session.RowBounds;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.stereotype.Component;
//
//import java.io.UnsupportedEncodingException;
//import java.lang.reflect.InvocationTargetException;
//
//import net.sf.jsqlparser.statement.Statement;
//import yashiro.metagross.core.hibernate.qbc.Criterions;
//
//import java.security.MessageDigest;
//import java.security.NoSuchAlgorithmException;
//import java.util.*;
//import java.util.concurrent.ThreadLocalRandom;
//import java.util.concurrent.TimeUnit;
//
//@Slf4j
//@Component
//@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
//        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
//public class MybatisInterceptor implements Interceptor {
//    @Autowired
//    @Qualifier("redis")
//    private RedisTemplate redisTemplate;
//
//    // 缓存时间 1天
//    private int expireOneDay = 24*60*60;
//
//    /**
//     * 正则匹配 insert、delete、update操作
//     */
//    private static final String REGEX = ".*INSERT\\\\u0020.*|.*DELETE\\\\u0020.*|.*UPDATE\\\\u0020.*";
//    private static final String REGEX_INSERT = "INSERT ";
//    private static final String REGEX_UPDATE = "UPDATE ";
//    private static final String REGEX_DELETE = "DELETE ";
//
//    private static final String PARAM_REGEX = "param\\d";
//
//    private static String redisKey = "microservices::method:%s:%s";
//    private static String EXCLUDE_REDIS_KEY = "microservices::exclude:method:%s:%s";
////    private static String redisKey = "microservices::method:%s:%s";
//
//    @Override
//    public Object intercept(Invocation invocation) throws Throwable {
//        return genSql(invocation);
//    }
//
//    public static void main(String[] args) {
//        //驼峰转下划线
//        String tableName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "DEMAND_INDENT");
//        System.out.println(tableName);
//        System.out.println("param1".matches(PARAM_REGEX));
//    }
//
//    public Object genSql(Invocation invocation) throws InvocationTargetException, IllegalAccessException {
//        //此处 执行SQL 语句
//        Object result = null;
//        //获取执行参数
//        Object[] objects = invocation.getArgs();
//        MappedStatement ms = (MappedStatement) objects[0];
//        BoundSql boundSql = ms.getSqlSource().getBoundSql(objects[1]);
//        String sql = boundSql.getSql().toLowerCase(Locale.CHINA).replace("[\\t\\n\\r]", " ");
//        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
//        Object parameterObject = boundSql.getParameterObject();
//        log.info("SQL 语句: {}", sql);
//        log.info("parameterMappings: {}", parameterMappings);
//        log.info("parameterObject: {}", parameterObject);
//
//        //去掉 空格 换行
//        sql = sqlHandler(sql);
//        Boolean pageFlag = false;
//        Map<String, Object> map = new HashMap<>();
//        //当前参数 若为多个
//        if (parameterObject instanceof MapperMethod.ParamMap) {
//            Map<String, Object> paramMap = (MapperMethod.ParamMap) parameterObject;
//            for (String key : paramMap.keySet()) {
//                if (!key.matches(PARAM_REGEX)) {
//                    Object value = paramMap.get(key);
//                    //判断参数为Map
//                    if (value instanceof HashMap) {
//                        map.putAll((Map<String, Object>) value);
//                    } else if (value!=null&&BeanUtil.isBean(value.getClass())) { //判断参数是否为对象
//                        if (value instanceof Page){
//                            pageFlag = true;
//                        }else if (value instanceof com.github.pagehelper.Page){
//                            pageFlag = true;
//                        }else {
//                            Map<String, Object> mapObj = BeanUtil.beanToMap(value);
//                            map.putAll(mapObj);
//                        }
//
//                    } else {
//                        map.put(key, value);
//                    }
//                }
//            }
//        } else {
//            for (ParameterMapping parameterMapping : parameterMappings) {
//                //获取请求参数
//                //获取#{var}中的key
//                String propertyName = parameterMapping.getProperty();
//                map.put(propertyName, parameterObject);
//
//            }
//        }
//
//
//        String clsName = null;
//
//
//        Set<String> tabNames = getTableNames(sql);
//        redisTemplate = SpringUtil.getBean("redis");
//        if (tabNames != null && tabNames.size() == 1&&!pageFlag) {
//            String tableName = (String) tabNames.toArray()[0];
//            String[] tableNameSplit = tableName.split("_");
//            String tableNameLast = "";
//            // 剔除前缀 例如 sys_user  -> user
//            for (int i = 0; i < tableNameSplit.length; i++) {
//                if (i != 0) {
//
//                    if (i == tableNameSplit.length-1) {
//                        tableNameLast += tableNameSplit[i];
//                    }else {
//                        tableNameLast += tableNameSplit[i]+"_";
//                    }
//                }
//            }
//            //下划线转 驼峰 大写
//            clsName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableNameLast);
//            String excludeRedisKey = generatorKey(map, clsName,EXCLUDE_REDIS_KEY);
//            Object excludeRedis = redisTemplate.opsForValue().get(excludeRedisKey);
//            if (excludeRedis!=null){
//                log.info("不走Redis 直接从数据库读取的类");
//                //此处 执行SQL 语句
//                result = invocation.proceed();
//                if (result instanceof ArrayList) {
//                    ArrayList resultList = (ArrayList) result;
//                    for (int i = 0; i < resultList.size(); i++) {
//                        clsName = resultList.get(i).getClass().getSimpleName();
//                        if (resultList.get(i) instanceof Map) {
//                            Map resultMap = (Map) resultList.get(i);
//                            log.info("结果集 ={}", resultMap);
//                        }
//                    }
//                }
//                return result;
//            }
//            String generatorKey = generatorKey(map, clsName,redisKey);
//
//
//            log.info("单表缓存 clsName = {}",clsName);
//            //如果是insert、delete、update操作 使用主库
//            if (sql.startsWith(REGEX_UPDATE)||sql.startsWith(REGEX_DELETE)||sql.startsWith(REGEX_INSERT)) {
////            if (sql.matches(REGEX)) {
//                String[] keySplit = generatorKey.split(":");
//                String key = generatorKey.replace(keySplit[keySplit.length-1],"").trim();
//                Set<String> keys = redisTemplate.keys(key + "*");
//                redisTemplate.delete(keys);
//                log.info("删除缓存 = {}",keys);
//
//                result = invocation.proceed();
//            } else {
//
//
//
//
//                result = redisTemplate.opsForValue().get(generatorKey);
//                log.info("从缓存中读取数据 key={} result={}",generatorKey, result);
//                if (result == null) {
//                    //此处 执行SQL 语句
//                    result = invocation.proceed();
//                    if (result instanceof ArrayList) {
//                        ArrayList resultList = (ArrayList) result;
//                        for (int i = 0; i < resultList.size(); i++) {
////                            clsName = resultList.get(i).getClass().getSimpleName();
//                            if (resultList.get(i) instanceof Map) {
//                                Map resultMap = (Map) resultList.get(i);
//                                log.info("结果集 ={}", resultMap);
//                            }
//                        }
//                        //缓存时间随机 1-3天
//                        final long liveTime = ThreadLocalRandom.current().nextInt(expireOneDay,3*expireOneDay);
//                        log.info("从数据库中 读取数据并 将数据存入缓存中  key={} result={} liveTime={}",generatorKey, result,liveTime);
//                        redisTemplate.opsForValue().set(generatorKey, result,liveTime, TimeUnit.MILLISECONDS);
//                    }
//                }
//
//            }
//
//        }else {
//            log.info("非单表查询 不走缓存 直接走数据库 处理");
//            //此处 执行SQL 语句
//            result = invocation.proceed();
//            if (result instanceof ArrayList) {
//                ArrayList resultList = (ArrayList) result;
//                for (int i = 0; i < resultList.size(); i++) {
//                    clsName = resultList.get(i).getClass().getSimpleName();
//                    if (resultList.get(i) instanceof Map) {
//                        Map resultMap = (Map) resultList.get(i);
//                        log.info("结果集 ={}", resultMap);
//                    }
//                }
//            }
//        }
//
//
//        return result;
//    }
//
//    private String generatorKey(Map<String, Object> map, String entityName,String key) {
//
//        String str = JSONObject.toJSONString(map);
//        byte[] hash = null;
//        String s = null;
//        try {
//            hash = MessageDigest.getInstance("MD5").digest(str.getBytes("UTF-8"));
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }
//        s = MD5.create().digestHex16(hash);//使用MD5生成位移key
//        return String.format(key, entityName, s);
//    }
//
//    private Map<String, Object> getParams(String sql) {
////        String[] whereSql = sql.split("where");
////        if (whereSql.length>0){
////            String[] orderSql = sql.split("order");
////            String params = null;
////            if (orderSql.length>0){
////                orderSql[0]
////            }
////
////            String[] paramsSql = whereSql[1].split("and");
////            if (paramsSql.length>1){
////                for (String params : paramsSql) {
////                    String key = params.split("=")[0];
////                    String value = params.split("=")[1];
////                }
////            }
////        }
////
////        String[] whereSql = sql.split("limit");
////        String[] whereSql = sql.split("group");
//        return null;
//    }
//
//
//    /**
//     * sql处理，去掉换行和多余空格
//     *
//     * @param sql
//     * @return
//     */
//    private String sqlHandler(String sql) {
//        String[] strings = sql.trim().replace("\n", " ").split("\\s+");
//        StringBuilder stringBuilder = new StringBuilder();
//        for (int i = 0; i < strings.length; i++) {
//            if (strings[i].endsWith(",")) {
//                stringBuilder.append(strings[i]);
//            } else {
//                stringBuilder.append(strings[i] + " ");
//            }
//        }
//        sql = stringBuilder.toString().trim().toUpperCase();
//        return sql;
//    }
//
//    /**
//     * @param sql
//     * @return 获取sql所有的表名
//     */
//    private Set<String> getTableNames(String sql) {
//        Statement statement = null;
//        try {
//            statement = CCJSqlParserUtil.parse(sql);
//        } catch (JSQLParserException e) {
//            throw new RuntimeException("解析sql语句错误！sql:" + sql, e);
//        }
//        TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
//        List<String> tableList = tablesNamesFinder.getTableList(statement);
//        Set<String> tableNames = new HashSet<>();
//        for (String tableName : tableList) {
//            //获取去掉“`”的表名
//            if (tableName.startsWith("`") && tableName.endsWith("`")) {
//                tableNames.add(tableName.substring(1, tableName.length() - 1));
//            } else {
//                tableNames.add(tableName);
//            }
//        }
//
//        return tableNames;
//    }
//
//
//    @Override
//    public Object plugin(Object o) {
//        //获取代理权
//        if (o instanceof Executor) {
//            //如果是Executor（执行增删改查操作），则拦截下来
//            return Plugin.wrap(o, this);
//        } else {
//            return o;
//        }
//    }
//
//    @Override
//    public void setProperties(Properties properties) {
//        //读取mybatis配置文件中属性
//    }
//}
//
